home *** CD-ROM | disk | FTP | other *** search
- /* Copyright 1990 by Christopher A. Wichura.
- See file GIFMachine.doc for full description of rights.
- */
-
- #include "GIFMachine.h"
- #include <dos/rdargs.h>
- #include <dos/dosasl.h>
- #include <dos/stdio.h>
- #include <workbench/startup.h>
-
- struct GIFdescriptor gdesc;
-
- struct RGB **BitPlane;
- struct RGB GlobalColourTable[256];
-
- extern UWORD *SHAMmem;
-
- extern BYTE *PlaneBuf;
-
- extern BOOL Laced;
-
- extern UBYTE *Planes[24];
-
- ULONG ImageNumber;
-
- extern struct MinList CommentList;
-
- /* indicates which memory list to allocate from */
- extern UWORD CurrentMem;
-
- /* the current GIF file handle */
- BPTR GIFfh = NULL;
-
- /* flag: display line counts during conversion or not */
- BOOL DisplayCounts;
-
- /* here we have some defines relating to our GADS call */
- #define ESC "\x1B["
- #define GIFMACH ESC "1;33;42mGIFMachine" ESC "0;32;40m"
-
- #define ARG_TEMPLATE "GIFfiles/A/M,TO/K,ALL/S,NOBORDER/N/K,XCOMP/S,DITHER/S,XFLIP/S,YFLIP/S,DEEP/S,NOCOUNT/S,BUFSIZE/N/K"
- enum ReadArgs {
- ARG_FILES,
- ARG_TO,
- ARG_ALL,
- ARG_NOBORD,
- ARG_XCOMP,
- ARG_DITHER,
- ARG_FLIPX,
- ARG_FLIPY,
- ARG_DEEP,
- ARG_NOCOUNT,
- ARG_BUFSIZ,
- ARG_sizeof
- };
-
- /* we will make the argument array global so that other modules can get at
- the ARG_TO, ARG_ALL and ARG_XCOMP fields easily */
- struct RDArgs *ArgsPtr;
- char *ArgArray[ARG_sizeof];
- BOOL ArgToIsDir;
-
- /* size of the read buffered i/o space */
- static ULONG BufSize = 2048; /* default size is 2k */
-
- int NoBorderLineThresh = 0;
-
- /* some mem pointers used when we do dithering */
- BYTE *CurrentLineErr[3];
- BYTE *LastLineErr[3];
-
- /* this flag says if we scaled the image */
- BOOL DidXComp;
-
- /* we print this when the user hits the break key */
- char *AbortMsg = "*** User Interruption!\n";
-
- /* storage for our library bases */
- struct Library *MathIeeeDoubBasBase = NULL;
- struct Library *IFFParseBase = NULL;
- struct Library *GfxBase = NULL;
-
- /* storage for our anchor when looking for pattern matches */
- struct Anchor {
- struct AnchorPath APath;
- char Path[256];
- } *anchor = NULL;
-
- /* here we have our main routine */
- int __regargs main(char *cmdptr, int cmdlen, struct WBStartup *WBMsg)
- {
- register char **FilesPtr;
- struct RDArgs MyArgs;
- extern UBYTE __far arg_help[];
- extern UBYTE __far VersionID[];
-
- InitMemory();
-
- if (WBMsg) {
- WarnMustUseCLI();
- MyExit(5);
- }
-
- if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37))) {
- MyPrintf("Unable to access %s!\n", "graphics.library");
- MyExit(5);
- }
-
- if (!(MathIeeeDoubBasBase = OpenLibrary("mathieeedoubbas.library", 0))) {
- MyPrintf("Unable to access %s!\n", "mathieeedoubbas.library");
- MyExit(5);
- }
-
- if (!(IFFParseBase = OpenLibrary("iffparse.library", 0))) {
- MyPrintf("Unable to access %s!\n", "iffparse.library");
- MyExit(5);
- }
-
- memset ((char *)&MyArgs, 0, sizeof(struct RDArgs));
-
- if (!(MyArgs.RDA_ExtHelp = (UBYTE *)MyAlloc(strlen(arg_help) + (2 * strlen(GIFMACH)) + strlen(VersionID) + 1))) {
- PutStr("Out of memory!\n");
- MyExit(5);
- }
-
- MySPrintf((char *)MyArgs.RDA_ExtHelp, arg_help, GIFMACH, VersionID, GIFMACH);
-
- if (!(ArgsPtr = ReadArgs(ARG_TEMPLATE, (LONG *)&ArgArray, &MyArgs))) {
- PrintFault(IoErr(), NULL);
- MyExit(5);
- }
-
- MyFree((char *)MyArgs.RDA_ExtHelp);
-
- if (ArgArray[ARG_TO])
- ArgToIsDir = IsDir(ArgArray[ARG_TO]);
-
- if (ArgArray[ARG_NOBORD]) {
- NoBorderLineThresh = *((LONG *)ArgArray[ARG_NOBORD]);
- if (NoBorderLineThresh < 0 || NoBorderLineThresh > 100) {
- PutStr("Invalid NOBORDER line threshhold specified.\n");
- MyExit(3);
- }
- }
-
- if (ArgArray[ARG_NOCOUNT])
- DisplayCounts = FALSE;
- else
- DisplayCounts = TRUE;
-
- if (ArgArray[ARG_BUFSIZ])
- BufSize = *((LONG *)ArgArray[ARG_BUFSIZ]) * 1024;
-
- if (!(FilesPtr = (char **)ArgArray[ARG_FILES])) {
- PutStr("No GIF files selected.\n");
- MyExit(3);
- }
-
- InitDiff(); /* one time init for the RGBdiff function */
-
- while (*FilesPtr)
- DoPattern(*FilesPtr++);
-
- MyExit(0);
- }
-
- void MyExit(ULONG result)
- {
- if (GIFfh)
- Close(GIFfh);
-
- if (IFFParseBase)
- CloseLibrary(IFFParseBase);
-
- if (MathIeeeDoubBasBase)
- CloseLibrary(MathIeeeDoubBasBase);
-
- if (GfxBase)
- CloseLibrary(GfxBase);
-
- if (anchor)
- MatchEnd(&anchor->APath);
-
- if (ArgsPtr)
- FreeArgs(ArgsPtr);
-
- FreeAll(1);
- FreeAll(0);
-
- XCEXIT(result);
- }
-
-
- /* this will walk through a pattern doing conversions */
- void DoPattern(char *pat)
- {
- register int error;
-
- if (!(anchor = (struct Anchor *)MyAlloc(sizeof(struct Anchor)))) {
- PutStr("Out of memory!\n");
- MyExit(10);
- }
-
- anchor->APath.ap_Strlen = sizeof(anchor->Path);
- anchor->APath.ap_Flags = APF_DOWILD;
- anchor->APath.ap_BreakBits = SIGBREAKF_CTRL_C;
-
- error = MatchFirst(pat, &anchor->APath);
-
- while (!error) {
- if (anchor->APath.ap_Info.fib_DirEntryType > 0) {
- if (ArgArray[ARG_ALL]) {
- if (!(anchor->APath.ap_Flags & APF_DIDDIR))
- anchor->APath.ap_Flags |= APF_DODIR;
- anchor->APath.ap_Flags &= ~APF_DIDDIR;
- }
- } else
- Convert(anchor->APath.ap_Buf);
-
- error = MatchNext(&anchor->APath);
- }
-
- MatchEnd(&anchor->APath);
- MyFree((char *)anchor);
- anchor = NULL;
-
- switch(error) {
- case ERROR_BREAK:
- PutStr(AbortMsg);
- MyExit(ABORTEXITVAL);
- break;
-
- case ERROR_OBJECT_NOT_FOUND:
- PutStr("File not found.\n");
- break;
-
- case ERROR_BUFFER_OVERFLOW:
- PutStr("Path too long!\n");
- break;
-
- case ERROR_NO_MORE_ENTRIES: /* normal termination */
- break;
-
- default:
- MyPrintf("I/O Error #%ld!\n", error);
- break;
- }
- }
-
- /* here we have the routine that gets ready to do the conversion */
- void Convert(char *name)
- {
- register int index;
- char *basename;
- char *ptr;
- char sig[7];
- int size;
- int error;
- int colours;
- LONG cmdcode;
-
- struct DateStamp StartTime, EndTime;
-
- CurrentMem++;
-
- if (!(GIFfh = Open(name, MODE_OLDFILE))) {
- MyPrintf("Error #%ld trying to open %s...\n", IoErr(), name);
- goto LeaveConvert;
- }
-
- SetVBuf(GIFfh, NULL, BUF_FULL, BufSize);
-
- sig[6] = NULL;
-
- if (FRead(GIFfh, sig, 1, 6) != 6 || strncmp("GIF", sig, 3)) {
- MyPrintf("%s is not a GIF file...\n", name);
- goto LeaveConvert;
- }
-
- MyPrintf("Converting %s ", name);
-
- basename = FilePart(name);
- ptr = basename + strlen(basename) - 4;
-
- if (!strnicmp(".gif", ptr, 4))
- *ptr = NULL;
-
- size = strlen(basename) + 6;
-
- if (ArgArray[ARG_TO]) {
- if (ArgToIsDir)
- size += strlen(ArgArray[ARG_TO]) + 1;
- else
- size = strlen(ArgArray[ARG_TO]) + 1;
- }
-
- if (!(ptr = MyAlloc(size))) {
- PutStr("... Out of memory!\n");
- goto LeaveConvert;
- }
-
- if (ArgArray[ARG_TO]) {
- strcpy(ptr, ArgArray[ARG_TO]);
-
- if (ArgToIsDir) {
- AddPart(ptr, basename, size);
- strcat(ptr, (ArgArray[ARG_DEEP] ? ".deep" : ".sham"));
- }
- } else {
- strcpy(ptr, basename);
- strcat(ptr, (ArgArray[ARG_DEEP] ? ".deep" : ".sham"));
- }
-
- MyPrintf("to %s...\n", ptr);
-
- DateStamp(&StartTime);
-
- if (FRead(GIFfh, (char *)&gdesc, 1, 7) != 7) {
- PutStr("Error reading screen descriptor.\n");
- goto LeaveConvert;
- }
-
- FlipWord(&gdesc.gd_Width);
- FlipWord(&gdesc.gd_Height);
-
- MyPrintf("Signature = \"%s\", Width = %ld, Height = %ld\n",
- sig, gdesc.gd_Width, gdesc.gd_Height);
-
- NewList((struct List *)&CommentList);
-
- DidXComp = 0;
- colours = 1L << ((gdesc.gd_ColInfo & 7) + 1);
-
- if (!(gdesc.gd_ColInfo & 1L << 7)) {
- PutStr("No global colour map supplied, using internal.\n");
-
- for (index = 0; index < colours; index++) {
- GlobalColourTable[index].rgb_Red =
- GlobalColourTable[index].rgb_Green =
- GlobalColourTable[index].rgb_Blue = index;
- }
- } else {
- MyPrintf("Global colour map contains %ld entries.\n", colours);
-
- for (index = 0; index < colours; index++) {
- if (FRead(GIFfh, &GlobalColourTable[index], 1, 3) != 3) {
- MyPrintf("Error reading global colour #%ld.\n",
- index);
- goto LeaveConvert;
- }
- }
- }
-
- size = ((gdesc.gd_Width + 7) / 8) + 1;
- size += (size + 127) >> 7;
-
- if (!(BitPlane = (struct RGB **)MyAlloc(gdesc.gd_Height * sizeof(struct RGB *))) ||
- !(SHAMmem = (UWORD *)MyAlloc(gdesc.gd_Height * 16 * sizeof(UWORD))) ||
- !(PlaneBuf = (BYTE *)MyAlloc(size))) {
- PutStr("Out of memory trying to allocate picture.\n");
- goto LeaveConvert;
- }
-
- size = (gdesc.gd_Width + 1) * sizeof(struct RGB);
-
- for (index = 0; index < gdesc.gd_Height; index++)
- if (!(BitPlane[index] = (struct RGB *)MyAlloc(size))) {
- PutStr("Out of memory trying to allocate picture.\n");
- goto LeaveConvert;
- }
-
- size = ((gdesc.gd_Width + 7) / 8) + 1;
- for (index = 0; index < (ArgArray[ARG_DEEP] ? 24 : 6); index++)
- if (!(Planes[index] = (UBYTE *)MyAlloc(size))) {
- PutStr("Out of memory trying to allocate picture.\n");
- goto LeaveConvert;
- }
-
- if (ArgArray[ARG_DITHER]) {
- size = gdesc.gd_Width * sizeof(BYTE);
-
- for (index = 0; index < 3; index++)
- if (!(CurrentLineErr[index] = (BYTE *)MyAlloc(size)) ||
- !(LastLineErr[index] = (BYTE *)MyAlloc(size))) {
- PutStr("Out of memory trying to allocate picture.\n");
- goto LeaveConvert;
- }
- }
-
- ImageNumber = 1;
-
- /* at this point we start looking for images, extensions or the gif
- terminator. we call the appropriate routine as we find each. */
-
- for (error = FALSE; error == FALSE;) {
- if ((cmdcode = FGetC(GIFfh)) == -1) {
- PutStr("...I/O error reading GIF file.\n");
- goto LeaveConvert;
- }
-
- switch(cmdcode) {
- case GIF_IMAGE:
- error = DoImage(GIFfh);
- break;
-
- case GIF_EXTENSION:
- error = DoExtension(GIFfh);
- break;
-
- case GIF_TERMINATOR:
- if (ArgArray[ARG_NOBORD])
- StripBorder();
-
- if (ArgArray[ARG_FLIPX])
- DoXFlip();
-
- if (ArgArray[ARG_FLIPY])
- DoYFlip();
-
- if (ArgArray[ARG_XCOMP]) {
- DoXComp();
- DidXComp = 1;
- }
-
- if (gdesc.gd_Height > 200 && DidXComp)
- Laced = TRUE;
- else
- Laced = FALSE;
-
- if (!ArgArray[ARG_DEEP]) {
- if (ArgArray[ARG_DITHER])
- DitherTo12();
- else
- ReduceTo12();
-
- GIFtoSHAM();
- }
-
- error = WriteIFF(ptr, (BOOL)ArgArray[ARG_DEEP]);
- break;
-
- default:
- MyPrintf("...Unknown directive #%ld encountered.\n",
- cmdcode);
- error = TRUE;
- }
- }
-
- DateStamp(&EndTime);
-
- {
- register ULONG Hours;
- register ULONG Minutes;
- register ULONG Seconds;
- register ULONG Seconds2;
-
- Seconds = (EndTime.ds_Days * 86400) + (EndTime.ds_Minute * 60) + (EndTime.ds_Tick / TICKS_PER_SECOND);
- Seconds2 = (StartTime.ds_Days * 86400) + (StartTime.ds_Minute * 60) + (StartTime.ds_Tick / TICKS_PER_SECOND);
-
- Seconds -= Seconds2;
-
- Hours = Seconds / 3600;
- Seconds -= Hours * 3600;
-
- Minutes = Seconds / 60;
- Seconds -= Minutes * 60;
-
- MyPrintf("...Conversion time was %ld hour%s, %ld minute%s and %ld second%s.\n",
- Hours, (Hours != 1 ? "s" : ""),
- Minutes, (Minutes != 1 ? "s" : ""),
- Seconds, (Seconds != 1 ? "s" : ""));
- }
-
- LeaveConvert:
- FreeAll(CurrentMem--);
-
- if (GIFfh) {
- Close(GIFfh);
- GIFfh = NULL;
- }
- }
-
- /* this will check to see if we have a directory or not */
- BOOL IsDir(char *name)
- {
- register BPTR lock;
- register BOOL result = FALSE;
-
- struct FileInfoBlock __aligned fib;
-
- if (lock = Lock(name, ACCESS_READ)) {
- if (Examine(lock, &fib)) {
- if (fib.fib_DirEntryType > 0)
- result = TRUE;
- }
- UnLock(lock);
- }
-
- return result;
- }
-
- /* this will convert a word from LSB/MSB to MSB/LSB */
- void FlipWord(UWORD *word)
- {
- register UBYTE swap1;
- register UBYTE swap2;
-
- swap1 = *word & 0xFF;
- swap2 = (*word & 0xFF00) >> 8;
- *word = swap1 << 8 | swap2;
- }
-